#pragma once

#include "../Util/Defines.hpp"
#include "cybertron/network/CybertronSyncConn.hpp"
class BridgeIOServer : public SocketTcpServer
{
public:
	BridgeIOServer();
	virtual ~BridgeIOServer();

	bool initialize();

	void run();

	void queueControlCommand(
		SocketBasePtr pSender,
		const Message& msg);

	void OnDisConnectClient(SocketBasePtr pSender);

	void FrameStep(int frame);

	void SendCaseStart();

	void SendCaseEnd();

	void SendFrameStart(int frame);

	void SendFrameEnd(int frame);

	void SendScenarioEvent(int mainVehicleId, const std::string * msgDataBody);
	void SendTrafficEvent(const std::string * msgDataBody);
	void SendEndTaskReason(int frame, const int endTaskReason);

	void SendMessageEventWriteOut(SocketBasePtr pSender, void* pbuffer, int length, Bridge::EOutSimOneMessageType type);
	// 
	void SendConfigReadResult(SocketBasePtr pSender, Message* pMessage, Bridge::EOutSimOneMessageType type);
	void SendConfigReadResult(SocketBasePtr pSender, void* pbuffer,int length, Bridge::EOutSimOneMessageType type);

	void SendMainVehicleStatus(int mainVehicleId, int ready);
	//
	void BroadcastMainVehicleNode(Message* pMessage);
	//
	void BroadcastAllNode(Message* pMessage);

	void SendToSimOneInMainVehicleNode(Message* pMessage, int id, Bridge::EBridgeClientType type);

	//
	void BroadcastOutSystemNode(Message* pMessage);
	//
	void SendHotareaDataSuberMainVehicle(int mainVehicleId, Message* pMessage);
	//
	void SendToOutSystemNode(Message* pMessage, int id, Bridge::EBridgeClientType type);
	
	void ReadEnvironmentInfo(SocketBasePtr pSender, Bridge::EOutSimOneMessageType type);
	void ReadSensorConfigurations(SocketBasePtr pSender, Bridge::EOutSimOneMessageType type);
	void ReadWayPoints(SocketBasePtr pSender, Bridge::EOutSimOneMessageType);

	void SendEnvironmentInfo(SocketBasePtr pSender,Bridge::EOutSimOneMessageType type);
	void SendSensorConfigurations(SocketBasePtr pSender,Bridge::EOutSimOneMessageType type);
	void SendWayPoints(SocketBasePtr pSender,Bridge::EOutSimOneMessageType);
	void SendHDMapInfo(SocketBasePtr pSender, Bridge::EOutSimOneMessageType);
	void SendCaseInfo(SocketBasePtr pSender, Bridge::EOutSimOneMessageType);
	void SendCaseStatus(SocketBasePtr pSender, Bridge::EOutSimOneMessageType);
	void SendMainVehicleList(SocketBasePtr pSender);
	void sendCaseStatusChange(int status);

	void sendRouteMessage(SocketBasePtr pSender, void* pBuffer, int length, int commandId);

	void AddConnHostVehicleClient(std::string hostVehicleId, bool isConnected, CybertronSyncConn client);
	void RemoveConnHostVehicleClient(CybertronSyncConn client);

	void SendToSimOneInMainVehicleNode(std::string hostVehicleId,void* pBuffer, int length, int commandId);
protected:
	virtual void onAccept(SocketBasePtr pRemoteSocket);

protected:
	struct Command {
		SocketBasePtr pSender;
		Message msg;

		void swap(Command& rhs)
		{
			std::swap(pSender, rhs.pSender);
			msg.swap(rhs.msg);
		}
	};
	uint32_t GetSensorType(std::uint32_t sensorType);
	void RunControlCommands();

	void executeControlCommand(Command& cmd);

	void zeroMembers();
	void clearThis();
	void onFromBridgeSimOneAPIReady(Command& cmd);
	void onFromBridgeTimeStepForwardConfirmDataMessage(Command& cmd);
	void onFromSensorAnyDataMessage(Command& cmd);
	void onFromMainVehicleDataMessage(Command& cmd);
	void onFromBridgeNodeRegisterReq(Command& cmd);
	void onFromBridgeReqSubMainVehicle(Command& cmd);
	
	void onFromBridgeMainVehicleListMessage(Command& cmd); 
	void onFromBridgeMainVehicleStatus(Command& cmd);

	void onFromBridgeMessageFromOut2SimOneWriteReq(Command& cmd);
	void onFromBridgeMessageSimOneOutReadReq(Command& cmd);
	void onFromBridgeMessageSimOneOutReadResult(Command& cmd);

	void onFromBridgeDataRouteMessage(Command& cmd);

	void onFromSignalLights(Command& cmd);
	void onFromBridgeVehicleBodyState(int hostVehicleId,Command& cmd);
	void onFromBridgeVehicleControlState(int hostVehicleId, Command& cmd);
	void onFromBridgeVehicleExtraState(int hostVehicleId, Command& cmd);
	void onFromBridgeVehicleEventInfo(int hostVehicleId, Command& cmd);
	void onFromBridgeVehicleTrajectoryState(int hostVehicleId, Command& cmd);
	void onFromDriverStatus(Command& cmd);
	void onFromDriverControl(Command& cmd);
	void onFromControlMode(Command& cmd);
	

	void eraseDisconnected();
	void AddBridageClient(SocketBasePtr pSender, int role, int id, int sync, int type, std::string alias);
	void removeBridageClient(SocketBasePtr pSender);
	void onFromEnvironmentInfo(Command& cmd, const std::string* msgDataBody);
private:

	//struct ConnHostVehicleClient{
	//	CybertronSyncConn client;
	//	std::string hostVehicleId;
	//	bool isConnected;
	//};
	typedef std::map<std::string, CybertronSyncConn> ConnHostVehicleClienMap;
	ConnHostVehicleClienMap mConnHostVehicleClienMap;

	struct BridgeClientNode
	{
		SocketBasePtr mSocket;
		int role;
		int id;
		int type;
		std::string alias;
		bool isSync;
		bool isConfirm;
		//bool isConnected;

		void send(Message& msg) {
			mSocket->send(msg);
		}
	};
	ConcurrentQueue<Command> mControlCommandQueue;

	mutable std::recursive_mutex mUnKnowClientNodesMutex;
	typedef std::map <std::string, BridgeClientNode> UnKnowClientNodesMap;
	UnKnowClientNodesMap mUnKnowClientNodesMap;

	mutable std::recursive_mutex mMainVehicleClientNodesMutex;
	typedef std::map <std::string, BridgeClientNode> MainVehicleClientNodesMap;
	MainVehicleClientNodesMap mMainVehicleClientNodesMap;

	mutable std::recursive_mutex mOutSystemClientNodesMutex;
	typedef std::map <std::string, BridgeClientNode> OutSystemClientNodesMap;
	OutSystemClientNodesMap mOutSystemClientNodesMap;


	std::map<int, std::string> mMainVehicleInfo;
	std::vector<SocketBasePtr> mSocketList;
	std::map<int, std::vector<SocketBasePtr>>mSubMainVehicleMap;
};